package fauxman.FauxManStates;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;

import fauxman.DynamicElements.Bonus;
import fauxman.DynamicElements.FauxMan;
import fauxman.DynamicElements.Food;
import fauxman.DynamicElements.Ghost;
import fauxman.DynamicElements.Pellet;
import fauxman.Enums.GameElementName;
import fauxman.StaticElements.PlayableArea;
import fauxman.interfaces.DynamicElement;
import fauxman.model.WorldModel;
import fauxman.states.EatenGhostState;
import fauxman.states.GhostState;
import fauxman.states.VulnerableGhostState;
import fauxman.utilities.ActionUtil;

public abstract class FauxManState {
	
	public abstract void setNextDirection(int[] action, WorldModel model, FauxMan fauxMan) ;

	public abstract Collection<? extends PlayableArea> getPlayableArea(WorldModel model); 

	public void draw(Graphics g, FauxMan fman) {
		g.drawImage(fman.getAppearance(), (int)fman.getContinuousPosition().getX(), (int)fman.getContinuousPosition().getY(), fman.getWidth(), fman.getHeight(), null); //TODO: look into Observer
		
		g.setColor(Color.YELLOW);
		g.fillRect((int)fman.getDiscretePosition().getX()*fman.getWidth(),(int)fman.getDiscretePosition().getY()*fman.getHeight(),fman.getHeight(),fman.getWidth());
		
		g.setColor(Color.GREEN);
		g.fillRect((int)fman.getConHitbox().getX(),(int)fman.getConHitbox().getY(),(int)fman.getConHitbox().getWidth(),(int)fman.getConHitbox().getHeight());

//		g.setColor(Color.BLUE);
//		g.fillRect((int)fman.getLookAhead().getX()*fman.getWidth(),(int)fman.getLookAhead().getY()*fman.getHeight(),fman.getHeight(),fman.getWidth());
	}

	public void collide(WorldModel model, DynamicElement de) {
		if(de.getEnum() == GameElementName.GHOST){
			Ghost g = (Ghost) de;
			System.out.println(g.getStates());
			LinkedList<GhostState> states = g.getStates();
			GhostState state = states.getLast();
			if(state == VulnerableGhostState.getInstance()){
				model.hitVulnerableGhost(g);
			} else if(state == EatenGhostState.getInstance()){
				//Do Nothing
			} else {
				model.hitAttackingGhost(g);
			}
		} else if(de.getEnum() == GameElementName.BONUS){
			model.ateBonus((Bonus)de);
			System.out.println("hit Bonus");
		} else if (de.getEnum() == GameElementName.PELLET){
			model.hitPellet((Pellet)de);
			System.out.println("hit Pellet");
		} else if (de.getEnum() == GameElementName.FOOD){
			model.ateFood((Food)de);
		} else {
			//FauxMan
			System.out.println(de.getClass());
		}
	}
	
	//Returns the updated direction that resulted from this position.  Returns null if this continous position didnt change the position.
	public int[] reactToCurrentContinuousPosition(WorldModel model, FauxMan fauxMan) {
		return null;
	}
	
	//Returns null for non cornering actions
	public FauxManCorneringAction convertToCorneringDirection(int conX, int conY, WorldModel model, int[] action)
	{
		FauxManCorneringAction cornerAction = null;
		int xPixel = (conX % model.PIXELS_PER_UNIT) / model.PRESENTATION_SCALER; //TODO: Make this prettier
		int yPixel = (conY % model.PIXELS_PER_UNIT) / model.PRESENTATION_SCALER;
		int PLAYABLE_AREA_X_TRACK = 3;
		int PLAYABLE_AREA_Y_TRACK = 4;
							
		int[] cornerDir = action;
		int trackLength = 0;
		
		//The intersection is (4, 5) using Java Graphic coordinates
		//The intersection is (4, 4) using cartesian coordinates
		if(yPixel == PLAYABLE_AREA_Y_TRACK) //Change the 4's and 5's to constant
		{
			trackLength = Math.abs( PLAYABLE_AREA_X_TRACK - xPixel);
			if(Arrays.equals(action, ActionUtil.NORTH))
			{
				if(xPixel < PLAYABLE_AREA_X_TRACK)
				{
					cornerDir = ActionUtil.NORTH_EAST;									
				} else if(xPixel > PLAYABLE_AREA_X_TRACK){
					cornerDir = ActionUtil.NORTH_WEST;
				}
				//if x = 4 then Want to remain North
			}
			else if(Arrays.equals(action, ActionUtil.SOUTH))
			{
				if(xPixel < PLAYABLE_AREA_X_TRACK)
				{
					cornerDir = ActionUtil.SOUTH_EAST;
				} else if(xPixel > PLAYABLE_AREA_X_TRACK){
					cornerDir = ActionUtil.SOUTH_WEST;
				}
				//if x = 4 then Want to remain SOUTH
			}
			else{
				trackLength = 0; 	//West and East should not be affected
			}
		}
		else if(xPixel == PLAYABLE_AREA_X_TRACK)
		{
			trackLength = Math.abs( PLAYABLE_AREA_Y_TRACK - yPixel);
			if(Arrays.equals(action, ActionUtil.WEST))
			{
				if(yPixel < PLAYABLE_AREA_Y_TRACK)
				{
					cornerDir = ActionUtil.SOUTH_WEST;
				} else if(yPixel > PLAYABLE_AREA_Y_TRACK){
					cornerDir = ActionUtil.NORTH_WEST;
				}
				//if y = 5 then Want to remain West
			}
			else if(Arrays.equals(action, ActionUtil.EAST))
			{
				if(yPixel < PLAYABLE_AREA_Y_TRACK)
				{
					cornerDir = ActionUtil.SOUTH_EAST;
				} else if(yPixel > PLAYABLE_AREA_Y_TRACK){
					cornerDir = ActionUtil.NORTH_EAST;
				}
				//if x = 5 then Want to remain SOUTH
			}
			else {
				trackLength = 0; //North and South should not be affected
			}
		}
		//If you are not on the main playable area track then you are on the cornering track.  Here you cannot reverse.  
		
		if(trackLength > 0 )
		{
			cornerAction = new FauxManCorneringAction(cornerDir, trackLength);
		}
			
		return cornerAction;
	}

}

class FauxManCorneringAction {
	private int[] direction;
	private int trackLength;
	
	public FauxManCorneringAction(int[] direction, int trackLength){
		this.direction = Arrays.copyOf(direction, direction.length);
		this. trackLength = trackLength;
	}
	public int[] getDirection(){
		return direction;
	}
	public int getTrackLength(){
		return trackLength;
	}
}